频繁的调用provider接太浪费了, 就有了将多个请求合并为一个请求的方式。
首先在provider中提供一个请求合并的接口:
@RestController public class UserController {
@GetMapping("/user/{ids}") public List<User> getUserByIds(@PathVariable String ids){ System.out.println(ids); String[] split = ids.split(","); List<User> user = new ArrayList<>(); for(String s : split){ User user1 = new User(); user1.setId(Integer.parseInt(s)); user.add(user1); } return user; } }
|
然后在Hystrix中定义UserService:
@Service public class UserService {
@Autowired RestTemplate restTemplate;
public List<User> getUsersByIds(List<Integer> ids){ User[] users = restTemplate.getForObject("http://provider/user/{1}", User[].class, StringUtils.join(ids, ",")); return Arrays.asList(users); } }
|
接下来定义 UserBatchCommand ,相当于我们之前的 HelloCommand:
public class UserBatchCommand extends HystrixCommand<List<User>> { private List<Integer> ids; private UserService userService;
public UserBatchCommand(List<Integer> ids, UserService userService) { super(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("batchCmd")).andCommandKey(HystrixCommandKey.Factory.asKey("batchKey"))); this.ids = ids; this.userService = userService; }
@Override protected List<User> run() throws Exception { return userService.getUsersByIds(ids); } }
|
一、最后定请求合并方法,【继承方式,做为了解】:
public class UserCollapseCommand extends HystrixCollapser<List<User>, User, Integer> { private UserService userService; private Integer id;
public UserCollapseCommand(UserService userService, Integer id) { super(HystrixCollapser.Setter.withCollapserKey(HystrixCollapserKey.Factory.asKey("UserCollapseCommand")).andCollapserPropertiesDefaults(HystrixCollapserProperties.Setter().withTimerDelayInMilliseconds(200))); this.userService = userService; this.id = id; }
@Override public Integer getRequestArgument() { return id; }
@Override protected HystrixCommand<List<User>> createCommand(Collection<CollapsedRequest<User, Integer>> collection) { List<Integer> ids = new ArrayList<>(collection.size()); for (CollapsedRequest<User, Integer> userIntegerCollapsedRequest : collection) { ids.add(userIntegerCollapsedRequest.getArgument()); } return new UserBatchCommand(ids, userService); }
@Override protected void mapResponseToRequests(List<User> users, Collection<CollapsedRequest<User, Integer>> collection) { int count = 0; for (CollapsedRequest<User, Integer> request : collection) { request.setResponse(users.get(count++)); } } }
|
然后测试调用:
@GetMapping("/hello5") public void hello5() throws ExecutionException,InterruptedException{ HystrixRequestContext ctx = HystrixRequestContext.initializeContext(); UserCollapseCommand cmd1 = new UserCollapseCommand(userService, 99); UserCollapseCommand cmd2 = new UserCollapseCommand(userService, 98); UserCollapseCommand cmd3 = new UserCollapseCommand(userService, 97);
Future<User> q1 = cmd1.queue(); Future<User> q2 = cmd2.queue(); Future<User> q3 = cmd3.queue();
User u1 = q1.get(); User u2 = q2.get(); User u3 = q3.get();
System.out.println(u1); System.out.println(u2); System.out.println(u3); Thread.sleep(2000); UserCollapseCommand cmd4 = new UserCollapseCommand(userService, 96); Future<User> q4 = cmd4.queue(); User u4 = q4.get(); System.out.println(u4); ctx.close();
}
|
二、通过注解实现请求合并【掌握】:
@Service public class UserService {
@Autowired RestTemplate restTemplate;
@HystrixCollapser(batchMethod = "getUsersByIds",collapserProperties = {@HystrixProperty(name = "timerDelayInMilliseconds",value = "200")}) public Future<User> getUserById(Integer id) { return null; }
@HystrixCommand public List<User> getUsersByIds(List<Integer> ids){ User[] users = restTemplate.getForObject("http://provider/user/{1}", User[].class, StringUtils.join(ids, ",")); return Arrays.asList(users); } }
|
测试方法:
@GetMapping("/hello6") public void hello6() throws ExecutionException, InterruptedException { HystrixRequestContext ctx = HystrixRequestContext.initializeContext(); Future<User> q1 = userService.getUserById(99); Future<User> q2 = userService.getUserById(98); Future<User> q3 = userService.getUserById(97); User u1 = q1.get(); User u2 = q2.get(); User u3 = q3.get(); System.out.println(u1); System.out.println(u2); System.out.println(u3); Thread.sleep(2000); Future<User> q4 = userService.getUserById(96); User u4 = q4.get(); System.out.println(u4); ctx.close(); }
|
小结 :@HystrixCollapser(batchMethod = “getUserByIds”,collapserProperties = {@HystrixProperty(name = “timerDelayInMilliseconds”,value = “200”)})
@HystrixCommand
代码地址:https://github.com/astronger/springcloud-simple-samples